/**
 * file gulp-package
 * created by mhb on 2018/7/9
 */
const gulp = require('gulp');
const $ = require('gulp-load-plugins')();
const runSequence = require('gulp-run-sequence'); // gulp 任务队列工具
const rollupStream = require('rollup');
const babel = require('rollup-plugin-babel'); // js 转义
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs'); // rollup commonjs 标准转义
const json = require('rollup-plugin-json'); // rollup json文件引入工具

const path = require('path');

// 服务启动工具
const spawn = require('child_process');
const browserSync = require('browser-sync').create();

// 获取刷新执行事件方法
const reload = browserSync.reload;


let config = {

  // 应用服务启动文件路径
  fork: path.resolve(__dirname, 'build/dev-gulp-forkserver'),
  src: {
    sass: 'src/static/style/**/*.scss',
    css: 'src/static/style/**/*.css',
    js: 'src/static/js/**/entry.*.js',
    fonts: 'src/static/fonts/**/*.{eot,svg,ttf,woff}',
    images: 'src/static/images/**/*.{jpg,jpeg,png,gif,svg,psd,cur,ico}'
  },
  dest: {
    sass: 'dist/static/style',
    css: 'dist/static/style',
    js: 'dist/static/js',
    fonts: 'dist/static/fonts',
    images: 'dist/static/images'
  },
  port: 9000
};


// 清理
gulp.task('clean', () => {
  return gulp.src('dist/')
    .pipe($.clean());
});

// copy 字体
gulp.task('fonts:copy', () => {
  return gulp.src(config.src.fonts)
    .pipe($.changed(config.dest.fonts, {
      hasChanged: $.changed.compareSha1Digest
    }))
    .pipe(gulp.dest(config.dest.fonts));
});

// copy 图片
gulp.task('images:copy', () => {
  return gulp.src(config.src.images)
    .pipe($.changed(config.dest.images, {
      hasChanged: $.changed.compareSha1Digest
    }))
    .pipe(gulp.dest(config.dest.images));
});

// css 样式
gulp.task('css:copy', () => {
  return gulp.src(config.src.css)
    .pipe($.changed(config.dest.css, {
      hasChanged: $.changed.compareSha1Digest
    }))
    .pipe(gulp.dest(config.dest.css));
});

// 编译sass,scss 文件
gulp.task('sass:build', () => {
  return gulp.src(config.src.sass)
    .pipe($.sourcemaps.init()) // 生产soucrcemap
    .pipe($.sass({
      outputStyle: 'compressed'
    }))
    .on('error', $.sass.logError)
    .pipe($.autoprefixer('last 2 version')) // 自动处理阅览器厂商前缀
    .pipe($.sourcemaps.write('./')) // 将sourcemaps写在当前目录下
    .pipe($.changed(config.dest.sass, {
      hasChanged: $.changed.compareSha1Digest
    }))
    .pipe(gulp.dest(config.dest.sass));
});

gulp.task('js:build', () => {
  return gulp.src(config.src.js, async (err, entries) => {
    if (err) {
      console.log(err);
    };
    const baseConf = {
      experimentalCodeSplitting: true,
      plugins: [
        resolve({
          jsnext: true
        }),
        commonjs(),
        babel({
          exclude: 'node_modules/**' // 排除 node_modules 目录下的
        }),
        json()
      ]
    };
    const outputConf = {
      format: 'cjs'
    };
    entries.forEach(async input => {
      await rollupStream.rollup(Object.assign({
        input
      }, baseConf)).then(bundle => bundle.write(Object.assign({
        file: input.replace('/src', '/dist'),
        name: path.basename(input).replace(/entry.(.+).js/, '$1')
      }, outputConf)));
    });
  });
});

gulp.task('build', cb => {
  return runSequence('clean', ['fonts:copy', 'images:copy', 'css:copy', 'sass:build', 'js:build'], cb);
});

// 监听文件变化重新做编译拷贝操作
gulp.task('watch', () => {
  gulp.watch(config.src.js, ['js:build']); // 监听js文件变化
  gulp.watch(config.src.sass, ['sass:build']); // 监听sass文件变化
  gulp.watch(config.src.css, ['css:copy']); // 监听css文件变化
  gulp.watch(config.src.fonts, ['fonts:copy']); // 监听fonts文件变化
  gulp.watch(config.src.images, ['images:copy']); // 监听images文件变化
});

gulp.task('server', ['build'], () => {
  startChildProcess(config.fork, msg => {
    // 启动代理
    browserSync.init({
      proxy: `http://0.0.0.0:${msg.port}`,
      notify: true,
      port: config.port,
      ui: false,
      startPath: '/'
    }, () => {});
  });

  // 监听源文件夹下如果有变更则，刷新页面 [后端文件，需要重启服务]
  gulp.watch(['./src/**/*.*', '!./src/static/**/*.*']).on('change', e => {
    console.log('Server file changed: ', e.path);
    startChildProcess(config.fork, () => {
      reload();
    });
  });

  // 监听源文件夹下如果有变更则，刷新页面[前端端文件，不需要重启服务]
  gulp.watch('dist/**').on('change', reload);
});

// 构建开发时默认的任务
gulp.task('default', ['server', 'watch']);

function startChildProcess(fork, cb) {
  startChildProcess.worker && startChildProcess.worker.kill('SIGINT');
  startChildProcess.worker = spawn.fork(fork);
  startChildProcess.worker.on('message', msg => {
    if (msg.action === 'start') {
      typeof cb === 'function' && cb(msg);
    }
  });
}
